package com.stp.oversold.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.stp.oversold.constant.R;
import com.stp.oversold.constant.aspect.ServiceLock;
import com.stp.oversold.entity.Payment;
import com.stp.oversold.entity.SecondKill;
import com.stp.oversold.entity.SuccessKilled;
import com.stp.oversold.mapper.PaymentMapper;
import com.stp.oversold.mapper.SecondKillMapper;
import com.stp.oversold.mapper.SuccessKilledMapper;
import com.stp.oversold.service.SecondKillService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@RequiredArgsConstructor
@Service
public class SecondKillServiceImpl extends ServiceImpl<SecondKillMapper, SecondKill> implements SecondKillService {

    private final SecondKillMapper secondKillMapper;
    private final SuccessKilledMapper successKilledMapper;
    private final PaymentMapper paymentMapper;

    /**
     * UPDATE锁表
     * @param skgId  商品id
     * @param userId    用户id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R startSecondKillByUpdateTwo(long skgId, long userId) {
        try {

            // 不校验，直接扣库存更新
            int result = secondKillMapper.updateSecondKillById(skgId);
            if (result > 0) {
                //创建订单
                SuccessKilled killed = new SuccessKilled();
                killed.setSecondKillId(skgId);
                killed.setUserId(userId);
                killed.setState(0);
                killed.setCreateTime(LocalDateTime.now());
                successKilledMapper.insert(killed);

                //支付
                Payment payment = new Payment();
                payment.setSecondKillId(skgId);
                payment.setUserId(userId);
                payment.setMoney(new BigDecimal(45));
                payment.setState(1);
                payment.setCreateTime(LocalDateTime.now());
                paymentMapper.insert(payment);
            } else {
                return R.ok();
            }
        } catch (Exception e) {
            throw new RuntimeException("异常了个乖乖");
        } finally {
        }
        return R.ok();
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public R startSecondKillByUpdate(long skgId, long userId) {
        try {
            // 校验库存-悲观锁
            SecondKill secondKill = secondKillMapper.querySecondKillForUpdate(skgId);
            Integer number = secondKill.getNumber();
            if (number > 0) {
                secondKill.setNumber(number - 1);
                secondKillMapper.updateById(secondKill);
                // 创建订单
                SuccessKilled killed = new SuccessKilled();
                killed.setSecondKillId(skgId);
                killed.setUserId(userId);
                killed.setState(0);
                killed.setCreateTime(LocalDateTime.now());
                successKilledMapper.insert(killed);

                // 模拟支付
                Payment payment = new Payment();
                payment.setSecondKillId(skgId);
                payment.setUserId(userId);
                payment.setMoney(new BigDecimal(100));
                payment.setState(1);
                payment.setCreateTime(LocalDateTime.now());
                paymentMapper.insert(payment);
            } else {
                return R.failed();
            }
        } catch (Exception e) {
            throw new RuntimeException("异常了个乖乖");
        }
        return R.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R startSecondKillByLock(long skgId, long userId) {
        try {
            // 校验库存
            SecondKill secondKill = secondKillMapper.selectById(skgId);
            Integer number = secondKill.getNumber();
            if (number > 0) {
                // 扣库存
                secondKill.setNumber(number - 1);
                secondKillMapper.updateById(secondKill);
                // 创建订单
                SuccessKilled killed = new SuccessKilled();
                killed.setSecondKillId(skgId);
                killed.setUserId(userId);
                killed.setState(0);
                killed.setCreateTime(LocalDateTime.now());
                successKilledMapper.insert(killed);

                // 模拟支付
                Payment payment = new Payment();
                payment.setSecondKillId(skgId);
                payment.setUserId(userId);
                payment.setMoney(new BigDecimal(100));
                payment.setState(1);
                payment.setCreateTime(LocalDateTime.now());
                paymentMapper.insert(payment);
            } else {
                return R.failed();
            }
        } catch (Exception e) {
            throw new RuntimeException("异常了个乖乖");
        }
        return R.ok();
    }

    @ServiceLock // 使用Aop进行加锁
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R startSecondKillByAop(long skgId, long userId) {
        try {
            // 校验库存
            SecondKill secondKill = secondKillMapper.selectById(skgId);
            Integer number = secondKill.getNumber();
            if (number > 0) {
                // 扣库存
                secondKill.setNumber(number - 1);
                secondKillMapper.updateById(secondKill);
                // 创建订单
                SuccessKilled killed = new SuccessKilled();
                killed.setSecondKillId(skgId);
                killed.setUserId(userId);
                killed.setState(0);
                killed.setCreateTime(LocalDateTime.now());
                successKilledMapper.insert(killed);

                // 模拟支付
                Payment payment = new Payment();
                payment.setSecondKillId(skgId);
                payment.setUserId(userId);
                payment.setMoney(new BigDecimal(100));
                payment.setState(1);
                payment.setCreateTime(LocalDateTime.now());
                paymentMapper.insert(payment);
            } else {
                return R.failed();
            }
        } catch (Exception e) {
            throw new RuntimeException("异常了个乖乖");
        }
        return R.ok();
    }
}
